/**
 * @file mysql_manager.cpp
 * @brief  基于 MySQL 连接池的数据库管理器实现
 */

 #include "mysql_manager.h"
 #include "sysconfig.h"
 #include "logger.hpp"
 #include "connpool.h"
 #include <cstring>
 #include <cstdio>
 
 MysqlManager& MysqlManager::getInstance()
 {
     static MysqlManager instance;
     return instance;
 }
 
 MysqlManager::MysqlManager()
 {
     pool_ = ConnectionPool::getConnectionPool();
 }
 
 /* ---------- 初始化 ---------- */
 bool MysqlManager::init()
 {
     std::lock_guard<std::mutex> lock(mutex_);
 
     if (!pool_)
     {
         Log::GetLogger("asynclogger")->Error("连接池未初始化");
         return false;
     }
 
     /* 简单探测是否能取到连接 */
     auto conn = pool_->getConnection();
     if (!conn)
     {
         Log::GetLogger("asynclogger")->Error("无法从连接池获取连接");
         return false;
     }
 
     if (!createTables())
     {
         Log::GetLogger("asynclogger")->Warn("创建数据表失败");
         return false;
     }
 
     Log::GetLogger("asynclogger")->Info("数据库初始化成功");
     return true;
 }
 
 /* ---------- 建表 ---------- */
 bool MysqlManager::createTables()
 {
     const char* sql = R"(
         CREATE TABLE IF NOT EXISTS file_mapping (
             id         VARCHAR(6)  PRIMARY KEY,
             hash       VARCHAR(64) UNIQUE NOT NULL,
             filename   VARCHAR(255) NOT NULL,
             filesize   BIGINT UNSIGNED NOT NULL,
             mime_type  VARCHAR(100),
             upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
             download_count INT UNSIGNED DEFAULT 0
         ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
         CREATE INDEX IF NOT EXISTS idx_hash        ON file_mapping(hash);
         CREATE INDEX IF NOT EXISTS idx_upload_time ON file_mapping(upload_time);
     )";
 
     auto conn = pool_->getConnection();
     if (!conn) return false;
 
     return conn->update(sql);
 }
 
 /* ---------- 插入 ---------- */
 bool MysqlManager::insertFile(const FileInfo& fi)
 {
     std::lock_guard<std::mutex> lock(mutex_);
 
     auto conn = pool_->getConnection();
     if (!conn) return false;
 
     /* 使用转义拼接，防止注入；生产环境建议改为预编译 */
     char sql[1024]{};
     std::snprintf(sql, sizeof(sql),
         "INSERT INTO file_mapping(id, hash, filename, filesize, mime_type, upload_time)"
         " VALUES('%s','%s','%s',%lu,'%s','%s')",
         fi.id.c_str(), fi.hash.c_str(), fi.filename.c_str(),
         fi.filesize, fi.mime_type.c_str(), fi.upload_time.c_str());
 
     return conn->update(sql);
 }
 
 /* ---------- 内部工具：单行结果 → FileInfo ---------- */
 static bool fetchRow(MYSQL_RES* res, FileInfo& fi)
 {
     MYSQL_ROW row = mysql_fetch_row(res);
     if (!row) return false;
 
     unsigned long* lens = mysql_fetch_lengths(res);
 
     fi.id            = std::string(row[0], lens[0]);
     fi.hash          = std::string(row[1], lens[1]);
     fi.filename      = std::string(row[2], lens[2]);
     fi.filesize      = std::strtoull(row[3], nullptr, 10);
     fi.mime_type     = std::string(row[4], lens[4]);
     fi.upload_time   = std::string(row[5], lens[5]);
     fi.download_count = std::atoi(row[6]);
     return true;
 }
 
 /* ---------- 按 id 查询 ---------- */
 bool MysqlManager::getFileById(const std::string& id, FileInfo& fi)
 {
     std::lock_guard<std::mutex> lock(mutex_);
 
     auto conn = pool_->getConnection();
     if (!conn) return false;
 
     char sql[256]{};
     std::snprintf(sql, sizeof(sql),
         "SELECT id,hash,filename,filesize,mime_type,upload_time,download_count"
         " FROM file_mapping WHERE id='%s' LIMIT 1", id.c_str());
 
     MYSQL_RES* res = conn->query(sql);
     if (!res) return false;
 
     bool ok = fetchRow(res, fi);
     mysql_free_result(res);
     return ok;
 }
 
 /* ---------- 按 hash 查询 ---------- */
 bool MysqlManager::getFileByHash(const std::string& hash, FileInfo& fi)
 {
     std::lock_guard<std::mutex> lock(mutex_);
 
     auto conn = pool_->getConnection();
     if (!conn) return false;
 
     char sql[256]{};
     std::snprintf(sql, sizeof(sql),
         "SELECT id,hash,filename,filesize,mime_type,upload_time,download_count"
         " FROM file_mapping WHERE hash='%s' LIMIT 1", hash.c_str());
 
     MYSQL_RES* res = conn->query(sql);
     if (!res) return false;
 
     bool ok = fetchRow(res, fi);
     mysql_free_result(res);
     return ok;
 }
 
 /* ---------- 下载次数 +1 ---------- */
 bool MysqlManager::updateDownloadCount(const std::string& id)
 {
     std::lock_guard<std::mutex> lock(mutex_);
 
     auto conn = pool_->getConnection();
     if (!conn) return false;
 
     char sql[128]{};
     std::snprintf(sql, sizeof(sql),
         "UPDATE file_mapping SET download_count=download_count+1 WHERE id='%s'", id.c_str());
 
     return conn->update(sql);
 }
 
 /* ---------- 存在性检测 ---------- */
 bool MysqlManager::isIdExists(const std::string& id)
 {
     std::lock_guard<std::mutex> lock(mutex_);
 
     auto conn = pool_->getConnection();
     if (!conn) return false;
 
     char sql[128]{};
     std::snprintf(sql, sizeof(sql),
         "SELECT 1 FROM file_mapping WHERE id='%s' LIMIT 1", id.c_str());
 
     MYSQL_RES* res = conn->query(sql);
     bool ok = (res && mysql_fetch_row(res));
     if (res) mysql_free_result(res);
     return ok;
 }
 
 bool MysqlManager::isHashExists(const std::string& hash)
 {
     std::lock_guard<std::mutex> lock(mutex_);
 
     auto conn = pool_->getConnection();
     if (!conn) return false;
 
     char sql[128]{};
     std::snprintf(sql, sizeof(sql),
         "SELECT 1 FROM file_mapping WHERE hash='%s' LIMIT 1", hash.c_str());
 
     MYSQL_RES* res = conn->query(sql);
     bool ok = (res && mysql_fetch_row(res));
     if (res) mysql_free_result(res);
     return ok;
 }
 